
package com.work.junit;

import static com.work.util.AppUtils.*;

import java.sql.Time;
import java.util.*;

import org.apache.commons.lang3.time.DateUtils;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.hibernate.type.*;
import org.junit.Test;

import com.work.calculations.LeaveCalculations;
import com.work.db.*;
import com.work.db.dao.*;
import com.work.db.entity.*;
import com.work.util.*;

public class DbTest {

	@Test
	public void loadUsers()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		for (BaseEntity entity : users()) {
			session.save(entity);
		}

		session.getTransaction().commit();
	}

	private List<BaseEntity> users()
	{
		List<BaseEntity> entityList = new ArrayList<>();

		User admin = new User();
		admin.setUserName("admin");
		admin.setPassword("admin");
		admin.setFirstName("admin");
		admin.setLastName("admin");
		admin.setSalt("KIN");

		entityList.add(admin);

		return entityList;
	}

	//@Test
	public void reloadTestData()
	{
		deleteAll();
		loadTestData();
	}

	//@Test
	public void deleteAll()
	{
		try {
			EntityUtils<WorkDay> entityUtils = new EntityUtils<WorkDay>(WorkDay.class);
			entityUtils.deleteAll();

			EntityUtils<LeavePerYear> leavePerYearUtils = new EntityUtils<LeavePerYear>(LeavePerYear.class);
			leavePerYearUtils.deleteAll();

			EntityUtils<Rate> rateUtils = new EntityUtils<Rate>(Rate.class);
			rateUtils.deleteAll();

			EntityUtils<Employer> employerUtils = new EntityUtils<Employer>(Employer.class);
			employerUtils.deleteAll();

			EntityUtils<Presents> presentsUtils = new EntityUtils<Presents>(Presents.class);
			presentsUtils.deleteAll();

			EntityUtils<LeaveOfAbsence> leaveUtils = new EntityUtils<LeaveOfAbsence>(LeaveOfAbsence.class);
			leaveUtils.deleteAll();

		} catch (Exception e) {
			Log.error(DbTest.class, "", e);
		}
	}

	@Test
	public void loadTestData()
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		for (BaseEntity entity : createTestData()) {
			session.save(entity);
		}

		session.getTransaction().commit();
	}

	private List<BaseEntity> createTestData()
	{
		List<BaseEntity> entityList = new ArrayList<>();

		EmployerDao employerDao = DaoFactoryImpl.instance().getEmployerDao();
		Employer employer = employerDao.findById(6L, false);

		Date dateFrom = createDate(2013, 7, 23);
		Date dateTo = createDate(2013, 9, 30);

		boolean dateBetween = true;
		Date date = dateFrom;

		Time workBeginTime = createTime(8, 30, 0);
		Time workEndTime = createTime(17, 0, 0);
		Time lunchBeginTime = createTime(12, 30, 0);
		Time lunchEndTime = createTime(13, 0, 0);

		List<WorkDay> workDaysInEmployer = new ArrayList<WorkDay>();

		while (dateBetween) {
			WorkDay workDay = new WorkDay();
			workDay.setDate(date);
			workDay.setEmployer(employer);
			workDaysInEmployer.add(workDay);

			if (!checkWeekend(date)) {
				Presents presents = new Presents();
				presents.setWorkBegin(workBeginTime);
				presents.setWorkEnd(workEndTime);
				presents.setLunchBegin(lunchBeginTime);
				presents.setLunchEnd(lunchEndTime);
				presents.setMinutes(presents.calculatePresentsTime());

				workDay.setPresentsType(PresentsTypeEnum.OBECNY);
				workDay.setPresents(presents);
				presents.setWorkDay(workDay);
			} else {
				workDay.setPresentsType(PresentsTypeEnum.WOLNE);
			}

			entityList.add(workDay);

			date = DateUtils.addDays(date, 1);
			if (date.after(dateTo)) {
				dateBetween = false;
			}
		}

		return entityList;
	}

	@Test
	public void getDaysForYear()
	{
		int year = 2012;
		Pair<Date, Date> daysPair = AppUtils.getLastAndFirstDayOfYear(year);
		Date firstDay = daysPair.getKey();
		Date lastDay = daysPair.getValue();

		WorkDayDao workDayDao = (WorkDayDao) DaoFactoryImpl.instance().getWorkDayDao();
		List<WorkDay> days = workDayDao.findByCriteria(Restrictions.between("date", firstDay, lastDay));
	}

	private void createLeave(LeaveTypeEnum state, String comment, WorkDay workDay)
	{
		LeaveOfAbsence abscence = new LeaveOfAbsence();
		abscence.setLeaveType(state);
		abscence.setComment(comment);
		abscence.setDayOfLeave(workDay);
		workDay.setPresentsType(PresentsTypeEnum.URLOP);
		workDay.setLeaveOfAbsence(abscence);
	}

	private void createOvertime(Time from, Time to, WorkDay workDay)
	{
		if (workDay.getOvertimes() == null) {
			workDay.setOvertimes(new ArrayList<Overtime>());
		}

		List<Overtime> overtimes = workDay.getOvertimes();
		Overtime overtime = new Overtime();
		overtime.setBegin(from);
		overtime.setEnd(to);
		overtime.setDescription("nadgodziny z CA");
		overtime.setWorkDay(workDay);
		overtime.setMinutes(overtime.calculateOverTime());

		overtimes.add(overtime);
	}

	@Test
	public void testNamedQuery()
	{
		List<NativeQueryParam> params = new ArrayList<NativeQueryParam>();
		params.add(new NativeQueryParam("year", 2013, false));

		WorkDayDao workDayDao = (WorkDayDao) DaoFactoryImpl.instance().getWorkDayDao();
		List<Integer> days = workDayDao.findByNativeQuery("SELECT distinct month(date) FROM workovertime.workday wd where year(date) = :year", params, Integer.class);
		for (Integer in : days) {
			System.out.println("DbTest.testNamedQuery(): " + in);
		}
	}

	@Test
	public void testNamedQuery2()
	{
		OvertimeDao workDayDao = (OvertimeDao) DaoFactoryImpl.instance().getOvertimeDao();
		List<Overtime> days = workDayDao.getOvertimes(null, 0);
		for (Overtime in : days) {
			System.out.println("DbTest.testNamedQuery2(): " + in);
		}
	}

	@Test
	public void testGetMonthWorkdays()
	{
		Date firstDay = AppUtils.getFirstDayOfMonth(2013, 0);
		Date firstDay2 = AppUtils.getFirstDayOfMonth(2013, 1);
		Date lastDay = AppUtils.getLastDayOfMonth(firstDay);

		WorkDayDao workDayDao = DaoFactoryImpl.instance().getWorkDayDao();
		//List<WorkDay> days = workDayDao.findByCriteria(Restrictions.between("date", firstDay, lastDay));
		List<WorkDay> days = workDayDao.findByCriteria(Restrictions.sqlRestriction(" {alias}.DATE between ? and ?", new Object[]{firstDay, firstDay2}, new Type[]{StandardBasicTypes.DATE, StandardBasicTypes.DATE}));
		for (WorkDay in : days) {
			System.out.println("WORKDAY: " + in.toString());
		}
	}

	@Test
	public void testGetRemainingLeave()
	{
		EmployerDao employerDao = DaoFactoryImpl.instance().getEmployerDao();
		Employer e = employerDao.findById(2L, false);

		int x = LeaveCalculations.instance().getRemainingLeave(e, 2011);

		System.out.println("DbTest.testGetRemainingLeave(): " + x);
	}

	@Test
	public void testGetOvertimeToTake()
	{
		LeaveDao leaveDao = DaoFactoryImpl.instance().getLeaveDao();
		List<NativeQueryParam> params = new ArrayList<NativeQueryParam>();
		params.add(new NativeQueryParam("employerId", 6));
		params.add(new NativeQueryParam("year", 2013));

		System.out.println("DbTest.testGetOvertimeToTake(): " + leaveDao.findOneByNativeQuery(SqlQuery.GET_OVERTIME_TO_TAKE, params, Integer.class));
	}

	@Test
	public void testGetTakenLeave()
	{
		EmployerDao employerDao = DaoFactoryImpl.instance().getEmployerDao();
		Employer employer = employerDao.findById(6L, false);

		List<LeaveTypeEnum> selectedLeaves = new ArrayList<LeaveTypeEnum>();
		selectedLeaves.add(LeaveTypeEnum.URLOP_WYPOCZYNKOWY);

		LeaveDao leaveDao = DaoFactoryImpl.instance().getLeaveDao();
		List<LeaveOfAbsence> leaves = leaveDao.getTakenLeaves(employer, selectedLeaves);

		for (LeaveOfAbsence leave : leaves) {
			System.out.println("LEAVE: " + leave.toString());
		}
	}
	
	@Test
	public void testInsertEmployment()
	{
		EmployerDao employerDao = DaoFactoryImpl.instance().getEmployerDao();
		Employer employer = employerDao.findById(6L, false);

		UserDao userDao = DaoFactoryImpl.instance().getUserDao();
		User user = userDao.findById(1L, false);
		
		Employment employment = new Employment();
		employment.setDateFrom(createDate(2011, 11, 15));
		employment.setEmployee(user);
		employment.setEmployer(employer);
		employment.setCurrent(true);
		
		EmploymentDao employmentDao = DaoFactoryImpl.instance().getEmploymentDao();
		employmentDao.save(employment);
	}

}
